package core;

import java.text.SimpleDateFormat;
import java.util.Calendar;

public class Date {
	private int day;
	private int month;
	private int year;

	private final String longDayPattern = "(0[1-9]|1[0-9]|2[0-9]|3[0-1])";
	private final String shortDayPattern = "([1-9])";
	private final String dayPattern = "(" + this.longDayPattern + "|" + this.shortDayPattern + ")";

	private final String longMonthPattern = "(0[1-9]|1[0-2])";
	private final String shortMonthPattern = "([1-9])";
	private final String monthPattern = "(" + this.longMonthPattern + "|" + this.shortMonthPattern + ")";

	private final String longYearPattern = "([1-2][0-9][0-9][0-9])";
	private final String shortYearPattern = "([0-9][0-9])";
	private final String yearPattern = "(" + this.longYearPattern + "|" + this.shortYearPattern + ")";

	private final String dotPattern = "(\\.|,)";

	/** 01.01.1999 / 1.1.99 */
	private final String pattern1 = this.dayPattern + this.dotPattern + this.monthPattern + this.dotPattern + this.yearPattern;
	/** 01/01/1999 */
	private final String pattern2 = this.dayPattern + "\\/" + this.monthPattern + "\\/" + this.yearPattern;
	/** 01 01 1999 */
	private final String pattern3 = this.dayPattern + " " + this.monthPattern + " " + this.yearPattern;
	/** 01011999 */
	private final String pattern4 = this.longDayPattern + "" + this.longMonthPattern + "" + this.yearPattern;
	/** 1999-12-31 */
	private final String pattern5 = this.yearPattern + "-" + this.monthPattern + "-" + this.dayPattern;

	public Date(int day, int month, int year) {
		this.day = day;
		this.month = month;
		this.year = year;
	}

	public Date(String date) {
		this.splitUpDate(date);
	}

	public String [] getDatePatterns() {
		return new String [] { this.pattern1, this.pattern2, this.pattern3, this.pattern4, this.pattern5 };
	}

	private void splitUpDate(String date) {

		if (date.matches(this.pattern1)) { // 01.01.1999
			String [] splitUp = date.split("\\.");
			this.setDay(Integer.parseInt(splitUp [0]));
			this.setMonth(Integer.parseInt(splitUp [1]));
			if (splitUp [2].length() == 2) {
				splitUp [2] = "19" + splitUp [2];
			}
			this.setYear(Integer.parseInt(splitUp [2]));
		} else if (date.matches(this.pattern2)) { // 01/01/1999
			String [] splitUp = date.split("\\/");
			this.setDay(Integer.parseInt(splitUp [0]));
			this.setMonth(Integer.parseInt(splitUp [1]));
			if (splitUp [2].length() == 2) {
				splitUp [2] = "19" + splitUp [2];
			}
			this.setYear(Integer.parseInt(splitUp [2]));
		} else if (date.matches(this.pattern3)) { // 01 01 1999
			String [] splitUp = date.split(" ");
			this.setDay(Integer.parseInt(splitUp [0]));
			this.setMonth(Integer.parseInt(splitUp [1]));
			if (splitUp [2].length() == 2) {
				splitUp [2] = "19" + splitUp [2];
			}
			this.setYear(Integer.parseInt(splitUp [2]));
		} else if (date.matches(this.pattern4)) { // 01011999
			this.setDay(Integer.parseInt(date.substring(0, 2)));
			this.setMonth(Integer.parseInt(date.substring(2, 4)));
			if (date.length() == 8) {
				this.setYear(Integer.parseInt(date.substring(4, 8)));
			} else {
				this.setYear(Integer.parseInt("19" + date.substring(4, 6)));
			}
		} else if (date.matches(this.pattern5)) { // 1999-12-31
			String [] splitUp = date.split("-");
			this.setDay(Integer.parseInt(splitUp [2]));
			this.setMonth(Integer.parseInt(splitUp [1]));
			if (splitUp [0].length() == 2) {
				splitUp [0] = "19" + splitUp [0];
			}
			this.setYear(Integer.parseInt(splitUp [0]));
		}
		/** no matching pattern */
		else {
			this.setDay(1);
			this.setMonth(1);
			this.setYear(1900);
		}
	}

	private boolean isValidDate(String toCheck) {
		if (toCheck.matches(this.pattern1)) {
			return true;
		} else if (toCheck.matches(this.pattern2)) {
			return true;
		} else if (toCheck.matches(this.pattern3)) {
			return true;
		} else if (toCheck.matches(this.pattern4)) {
			return true;
		} else if (toCheck.matches(this.pattern5)) {
			return true;
		} else {
			return false;
		}
	}

	public int getDay() {
		return this.day;
	}

	public int getMonth() {
		return this.month;
	}

	public int getYear() {
		return this.year;
	}

	public void setDay(int day) {
		this.day = day;
	}

	public void setMonth(int month) {
		this.month = month;
	}

	public void setYear(int year) {
		this.year = year;
	}

	@Override
	public String toString() {
		StringBuilder output = new StringBuilder();
		if (this.day < 10) {
			output.append("0");
		}
		output.append(this.day);
		output.append(".");
		if (this.month < 10) {
			output.append("0");
		}
		output.append(this.month);
		output.append(".");
		output.append(this.year);

		return output.toString();
	}

	/**
	 * @return the current date (==today)
	 */
	public static Date getCurrentDate() {
		Calendar cal = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
		return new Date(sdf.format(cal.getTime()).toString());
	}

	public static int getAge(Date birthDate) {
		int age;

		Date now = getCurrentDate();

		if (birthDate.getMonth() > now.getMonth()) {
			age = now.getYear() - birthDate.getYear() - 1;
		} else if ((birthDate.getMonth() == now.getMonth()) && (birthDate.getDay() > now.getDay())) {
			age = now.getYear() - birthDate.getYear() - 1;
		} else {
			age = now.getYear() - birthDate.getYear();
		}
		return age;
	}

	@Override
	public boolean equals(Object object) {
		if (object instanceof Date) {
			if (((Date) object).getDay() == this.day) {
				if (((Date) object).getMonth() == this.month) {
					if (((Date) object).getYear() == this.year) {
						return true;
					}
				}
			}
		}
		return false;
	}

}
